#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "borwein.h"
#include "monteCarlo.h"
#include "blackScholes.h"
#include "gaussLegendre.h"

#define METODO_GAUSS_LEGENDRE   'A'
#define METODO_BORWEIN          'B'
#define METODO_MONTE_CARLO      'C'
#define METODO_BLACK_SCHOLES    'D'


int main(int argc, char* argv[])
{
    srand(time(NULL));

    char metodo, paralelo;
    long int iterations;

    // Para black scholes
    double S,    // Valor da acao
            E,      // Preco do exercicio da opcao
            r,      // Taxa de juros
            sig,    // Volatilidade da acao
            T;      // Tempo de validade da opcao

    if ( scanf( "%c %ld %c", &metodo, &iterations, &paralelo ) != 3)
    {
        printf("Invalid input!");
        exit(1);
    }

    if (paralelo == 'p') // Multi-Thread version
    {
        int threads = 4;
        scanf( "%d", &threads );
        if (threads <= 0)
        {
            printf("Invalid number of threads!");
            exit(1);
        }

        switch (metodo)
        {
            case METODO_GAUSS_LEGENDRE:
                gaussLegendre_paralelo(iterations, threads);
                break;

            case METODO_BORWEIN:
                borwein_paralelo(iterations, threads);
                break;

            case METODO_MONTE_CARLO:
                monteCarlo_paralelo(iterations, threads);
                break;

            case METODO_BLACK_SCHOLES:
                // Ler dados do blackscholes
                scanf("%lf %lf %lf %lf %lf", &S, &E, &r, &sig, &T);

                blackScholes_paralelo(S, E, r, sig, T, iterations, threads);
                break;

            default:
                printf("Invalid method!\n");
                exit(1);
                break;
        }
    }else if (paralelo == 's'){ // Single-Thread version
        switch (metodo)
        {
            case METODO_GAUSS_LEGENDRE:
                gaussLegendre_sequencial(iterations);
                break;

            case METODO_BORWEIN:
                borwein_sequencial(iterations);
                break;

            case METODO_MONTE_CARLO:
                monteCarlo_sequencial(iterations);
                break;

            case METODO_BLACK_SCHOLES:
                // Ler dados do blackscholes
                scanf("%lf %lf %lf %lf %lf", &S, &E, &r, &sig, &T);

                blackScholes_seq(S, E, r, sig, T, iterations);
                break;

            default:
                printf("Invalid method!\n");
                exit(1);
                break;
        }
    }else{
        printf("Invalid execution mode!\n");
        exit(1);
    }

    return 0;
}

